/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package mrp.persistencia.controller;

import java.io.Serializable;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import mrp.persistencia.entity.Pedido;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.transaction.UserTransaction;
import mrp.beans.util.EntityManagerUtil;
import mrp.persistencia.controller.exceptions.IllegalOrphanException;
import mrp.persistencia.controller.exceptions.NonexistentEntityException;
import mrp.persistencia.controller.exceptions.PreexistingEntityException;
import mrp.persistencia.controller.exceptions.RollbackFailureException;
import mrp.persistencia.entity.Cliente;
import mrp.persistencia.entity.Empresa;
import mrp.persistencia.entity.Persona;

/**
 *
 * @author root
 */
public class ClienteJpaController implements Serializable {

    public ClienteJpaController() {
        
        this.emf = EntityManagerUtil.getEntityManagerFactory();
    }

    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }
    public boolean create(Object objeto,String entidad) throws PreexistingEntityException,RollbackFailureException, Exception {
        //tipo persona, empresa, pedido
        boolean creo=false;
        if(entidad.equals("Persona"))
        {
            Persona persona=(Persona)objeto;
            EntityManager em = null;
            try {
                em = getEntityManager();
                em.getTransaction().begin();
                em.persist(persona);
                em.getTransaction().commit();
                creo=true;
            } catch (Exception ex) {
                if (findCliente(persona.getNumerocliente()) != null) {
                    throw new PreexistingEntityException("Cliente " + persona.getNumerocliente() + " ya existe en el sistema!", ex);
                } 
                if (findClientePersonaEmpresaUK(persona.getNumerocedula(), "Persona")!= null) {
                    //System.out.println("entro en findCliente(persona.getNumerocedula() = "+findCliente(persona.getNumerocedula()));
                    throw new PreexistingEntityException("El cliente con el numero de cedula: "+persona.getNumerocedula()+" que desea crear ya existe en el sistema!", ex);
                } 
                //System.out.println("pasooooo = "+ex.getMessage()+ " persona.getNumerocedula()="+persona.getNumerocedula()+" findCliente(persona.getNumerocedula() = "+findCliente(persona.getNumerocedula()));
                throw ex;
            } finally {
                if (em != null) {
                    em.close();

                }
            }
        }
        else if(entidad.equals("Empresa"))
        {
            Empresa empresa=(Empresa)objeto;
            EntityManager em = null;
            try {
                em = getEntityManager();
                em.getTransaction().begin();
                em.persist(empresa);
                em.getTransaction().commit();
                creo=true;
            } catch (Exception ex) {
                if (findCliente(empresa.getNumerocliente()) != null) {
                    throw new PreexistingEntityException("Cliente " + empresa.getNumerocliente() + " ya existe en el sistema!", ex);
                } 
                if (findClientePersonaEmpresaUK(empresa.getRuc(), "Empresa")!= null) {
                    //System.out.println("entro en findCliente(persona.getNumerocedula() = "+findCliente(persona.getNumerocedula()));
                    throw new PreexistingEntityException("El cliente con el numero de RUC: "+empresa.getRuc()+" que desea crear ya existe en el sistema!", ex);
                } 
                //System.out.println("pasooooo = "+ex.getMessage()+ " persona.getNumerocedula()="+persona.getNumerocedula()+" findCliente(persona.getNumerocedula() = "+findCliente(persona.getNumerocedula()));
                throw ex;
            } finally {
                if (em != null) {
                    em.close();

                }
            }
        }
        else if(entidad.equals("Pedido"))
        {
            Cliente cliente=(Cliente)objeto;
            if (cliente.getPedidoList() == null) {
                cliente.setPedidoList(new ArrayList<Pedido>());
            }
            EntityManager em = null;
            try {
                em = getEntityManager();
                em.getTransaction().begin();
                List<Pedido> attachedPedidoList = new ArrayList<Pedido>();
                for (Pedido pedidoListPedidoToAttach : cliente.getPedidoList()) {
                    pedidoListPedidoToAttach = em.getReference(pedidoListPedidoToAttach.getClass(), pedidoListPedidoToAttach.getNumeroordencompra());
                    attachedPedidoList.add(pedidoListPedidoToAttach);
                }
                cliente.setPedidoList(attachedPedidoList);
                em.persist(cliente);
                for (Pedido pedidoListPedido : cliente.getPedidoList()) {
                    Cliente oldClienteFkOfPedidoListPedido = pedidoListPedido.getClienteFk();
                    pedidoListPedido.setClienteFk(cliente);
                    pedidoListPedido = em.merge(pedidoListPedido);
                    if (oldClienteFkOfPedidoListPedido != null) {
                        oldClienteFkOfPedidoListPedido.getPedidoList().remove(pedidoListPedido);
                        oldClienteFkOfPedidoListPedido = em.merge(oldClienteFkOfPedidoListPedido);
                    }
                }
                em.getTransaction().commit();
                creo=true;
            } catch (Exception ex) {
                try {
                    em.getTransaction().rollback();
                } catch (Exception re) {
                    throw new RollbackFailureException("An error occurred attempting to roll back the transaction.", re);
                }
                if (findCliente(cliente.getNumerocliente()) != null) {
                    throw new PreexistingEntityException("Cliente " + cliente + " already exists.", ex);
                }
                throw ex;
            } finally {
                if (em != null) {
                    em.close();
                }
            }
        }
        return creo;
    }

    public boolean edit(Object objeto, String entidad) throws IllegalOrphanException, NonexistentEntityException, RollbackFailureException, Exception {
        
        boolean edito=false;
        if(entidad.equals("Persona"))
        {
            Persona persona=(Persona)objeto;
            EntityManager em = null;
            try {
                em = getEntityManager();
                em.getTransaction().begin();
                persona=em.merge(persona);
                em.getTransaction().commit();
                edito=true;
            } catch (Exception ex) {
                if (findCliente(persona.getNumerocliente()) == null) {
                    throw new NonexistentEntityException("El Cliente " + persona.getNumerocliente() + " no existe en el sistema!", ex);
                } 
                if (findClientePersonaEmpresaUK(persona.getNumerocedula(), "Persona")== null) {
                    //System.out.println("entro en findCliente(persona.getNumerocedula() = "+findCliente(persona.getNumerocedula()));
                    throw new NonexistentEntityException("El cliente con el numero de cedula: "+persona.getNumerocedula()+" no existe en el sistema!", ex);
                } 
                //System.out.println("pasooooo = "+ex.getMessage()+ " persona.getNumerocedula()="+persona.getNumerocedula()+" findCliente(persona.getNumerocedula() = "+findCliente(persona.getNumerocedula()));
                throw ex;
            } finally {
                if (em != null) {
                    em.close();

                }
            }
        }
        else if(entidad.equals("Empresa"))
        {
            Empresa empresa=(Empresa)objeto;
            EntityManager em = null;
            try {
                em = getEntityManager();
                em.getTransaction().begin();
                empresa=em.merge(empresa);
                em.getTransaction().commit();
                edito=true;
            } catch (Exception ex) {
                if (findCliente(empresa.getNumerocliente()) == null) {
                    throw new NonexistentEntityException("El Cliente " + empresa.getNumerocliente() + " no existe en el sistema!", ex);
                } 
                if (findClientePersonaEmpresaUK(empresa.getRuc(), "Empresa")== null) {
                    //System.out.println("entro en findCliente(persona.getNumerocedula() = "+findCliente(persona.getNumerocedula()));
                    throw new NonexistentEntityException("El cliente con el numero de RUC: "+empresa.getRuc()+" no existe en el sistema!", ex);
                } 
                //System.out.println("pasooooo = "+ex.getMessage()+ " persona.getNumerocedula()="+persona.getNumerocedula()+" findCliente(persona.getNumerocedula() = "+findCliente(persona.getNumerocedula()));
                throw ex;
            } finally {
                if (em != null) {
                    em.close();

                }
            }
        }
        else if(entidad.equals("Pedido"))
        {
            Cliente cliente=(Cliente)objeto;
            EntityManager em = null;
            try {

                em = getEntityManager();
                em.getTransaction().begin();
                Cliente persistentCliente = em.find(Cliente.class, cliente.getNumerocliente());
                List<Pedido> pedidoListOld = persistentCliente.getPedidoList();
                List<Pedido> pedidoListNew = cliente.getPedidoList();
                List<String> illegalOrphanMessages = null;
                for (Pedido pedidoListOldPedido : pedidoListOld) {
                    if (!pedidoListNew.contains(pedidoListOldPedido)) {
                        if (illegalOrphanMessages == null) {
                            illegalOrphanMessages = new ArrayList<String>();
                        }
                        illegalOrphanMessages.add("You must retain Pedido " + pedidoListOldPedido + " since its clienteFk field is not nullable.");
                    }
                }
                if (illegalOrphanMessages != null) {
                    throw new IllegalOrphanException(illegalOrphanMessages);
                }
                List<Pedido> attachedPedidoListNew = new ArrayList<Pedido>();
                for (Pedido pedidoListNewPedidoToAttach : pedidoListNew) {
                    pedidoListNewPedidoToAttach = em.getReference(pedidoListNewPedidoToAttach.getClass(), pedidoListNewPedidoToAttach.getNumeroordencompra());
                    attachedPedidoListNew.add(pedidoListNewPedidoToAttach);
                }
                pedidoListNew = attachedPedidoListNew;
                cliente.setPedidoList(pedidoListNew);
                cliente = em.merge(cliente);
                for (Pedido pedidoListNewPedido : pedidoListNew) {
                    if (!pedidoListOld.contains(pedidoListNewPedido)) {
                        Cliente oldClienteFkOfPedidoListNewPedido = pedidoListNewPedido.getClienteFk();
                        pedidoListNewPedido.setClienteFk(cliente);
                        pedidoListNewPedido = em.merge(pedidoListNewPedido);
                        if (oldClienteFkOfPedidoListNewPedido != null && !oldClienteFkOfPedidoListNewPedido.equals(cliente)) {
                            oldClienteFkOfPedidoListNewPedido.getPedidoList().remove(pedidoListNewPedido);
                            oldClienteFkOfPedidoListNewPedido = em.merge(oldClienteFkOfPedidoListNewPedido);
                        }
                    }
                }
                em.getTransaction().commit();
            } catch (Exception ex) {
                try {
                    em.getTransaction().rollback();
                } catch (Exception re) {
                    throw new RollbackFailureException("An error occurred attempting to roll back the transaction.", re);
                }
                String msg = ex.getLocalizedMessage();
                if (msg == null || msg.length() == 0) {
                    String id = cliente.getNumerocliente();
                    if (findCliente(id) == null) {
                        throw new NonexistentEntityException("The cliente with id " + id + " no longer exists.");
                    }
                }
                throw ex;
            } finally {
                if (em != null) {
                    em.close();
                }
            }
        }
        return edito;
    }

    public void destroy(String id,String entidad) throws IllegalOrphanException, NonexistentEntityException, RollbackFailureException, Exception {
        EntityManager em = null;
        if(entidad.equals("Persona"))
        {
                try {
                em = getEntityManager();
                em.getTransaction().begin();
                Persona persona;
                try {
                    persona = em.getReference(Persona.class, id);
                    persona.getNumerocliente();
                } catch (EntityNotFoundException enfe) {
                    throw new NonexistentEntityException("El cliente con código " + id + " no existe en el sistema.", enfe);
                }
                em.remove(persona);
                em.getTransaction().commit();
            } finally {
                if (em != null) {
                    em.close();
                }
            }
        }
        else if(entidad.equals("Empresa"))
        {
                try {
                em = getEntityManager();
                em.getTransaction().begin();
                Empresa empresa;
                try {
                    empresa = em.getReference(Empresa.class, id);
                    empresa.getNumerocliente();
                } catch (EntityNotFoundException enfe) {
                    throw new NonexistentEntityException("El cliente con código  " + id + " no existe en el sistema.", enfe);
                }
                em.remove(empresa);
                em.getTransaction().commit();
            } finally {
                if (em != null) {
                    em.close();
                }
            }
        }
        else if(entidad.equals("Pedido"))
        {
            try {

                em = getEntityManager();
                em.getTransaction().begin();
                Cliente cliente;
                try {
                    cliente = em.getReference(Cliente.class, id);
                    cliente.getNumerocliente();
                } catch (EntityNotFoundException enfe) {
                    throw new NonexistentEntityException("El cliente con código " + id + " no existe.", enfe);
                }
                List<String> illegalOrphanMessages = null;
                List<Pedido> pedidoListOrphanCheck = cliente.getPedidoList();
                for (Pedido pedidoListOrphanCheckPedido : pedidoListOrphanCheck) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("This Cliente (" + cliente + ") cannot be destroyed since the Pedido " + pedidoListOrphanCheckPedido + " in its pedidoList field has a non-nullable clienteFk field.");
                }
                if (illegalOrphanMessages != null) {
                    throw new IllegalOrphanException(illegalOrphanMessages);
                }
                em.remove(cliente);
                em.getTransaction().commit();
            } catch (Exception ex) {
                try {
                    em.getTransaction().rollback();
                } catch (Exception re) {
                    throw new RollbackFailureException("An error occurred attempting to roll back the transaction.", re);
                }
                throw ex;
            } finally {
                if (em != null) {
                    em.close();
                }
            }
        }
    }

    public List<Cliente> findClienteEntities() {
        return findClienteEntities(true, -1, -1);
    }

    public List<Cliente> findClienteEntities(int maxResults, int firstResult) {
        return findClienteEntities(false, maxResults, firstResult);
    }

    private List<Cliente> findClienteEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Cliente.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Cliente findCliente(String id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Cliente.class, id);
        } finally {
            em.close();
        }
    }

    public int getClienteCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Cliente> rt = cq.from(Cliente.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }
    public List<Cliente> findClienteOrderByAll() {
        return findClienteOrderBy(true, -1, -1);
    }

    public List<Cliente> findClienteOrderByLazy(int maxResults, int firstResult) {
        return findClienteOrderBy(false, maxResults, firstResult);
    }

    private List<Cliente> findClienteOrderBy(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
//            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
//            cq.select(cq.from(Cliente.class));
//            Query q = em.createQuery(cq);
            Query q = em.createQuery("SELECT o FROM Cliente o order by o.numerocliente");
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }
    
    public List<Cliente> findClienteWhereOrderBy(String consulta,boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
//            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
//            cq.select(cq.from(Cliente.class));
//            Query q = em.createQuery(cq);
//            Query q = em.createQuery("SELECT o FROM Cliente o where "+ +" order by o.numerocliente");
            Query q = em.createQuery(consulta);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }
    public Object findClientePersonaEmpresaUK(String unique,String entidad) {
        EntityManager em = getEntityManager();
        try {
//            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
//            cq.select(cq.from(Cliente.class));
//            Query q = em.createQuery(cq);
//            Query q = em.createQuery("SELECT o FROM Cliente o where "+ +" order by o.numerocliente");
            
            String columna="numerocedula";
            if(entidad.equals("Empresa"))
             columna="ruc";
            Query q = em.createQuery("Select o from "+entidad+" as o where o."+columna+" = '"+unique+"'");
            
            return q.getSingleResult();
        } finally {
            em.close();
        }
    }
    public List<Persona> findClientePersonaWhereOrderBy(String consulta,boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
//            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
//            cq.select(cq.from(Cliente.class));
//            Query q = em.createQuery(cq);
//            Query q = em.createQuery("SELECT o FROM Cliente o where "+ +" order by o.numerocliente");
            Query q = em.createQuery(consulta);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }
    public List<Empresa> findClienteEmpresaWhereOrderBy(String consulta,boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
//            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
//            cq.select(cq.from(Cliente.class));
//            Query q = em.createQuery(cq);
//            Query q = em.createQuery("SELECT o FROM Cliente o where "+ +" order by o.numerocliente");
            Query q = em.createQuery(consulta);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }
    
}
